using SumerCoreDevOps.Infrastructure.Tcp;
using SumerCoreDevOps.Infrastructure.Libraries;
using SumerCoreDevOps.Infrastructure.Security;
using SumerCoreDevOps.ExecuteNodeApi.Services;
using SumerCoreDevOps.ExecuteNodeApi.Handlers;
using SumerCoreDevOps.Shared.Enums;
using SumerCoreDevOps.Shared.Models.Messages;
using System.Text;

// 检查是否是命令行模式
if (args.Length > 0 && args[0] == "register")
{
    // 使用命令行接口
    return await SumerCoreDevOps.ExecuteNodeApi.CommandLineInterface.RunAsync(args);
}

var builder = WebApplication.CreateBuilder(args);

// ========================================
// 📝 处理命令行参数并注入到配置
// ========================================
var joinTokenArg = args.FirstOrDefault(a => a.StartsWith("--join-token="));
if (!string.IsNullOrEmpty(joinTokenArg))
{
    var joinToken = joinTokenArg.Split('=')[1];
    builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
    {
        ["Server:JoinToken"] = joinToken
    });
    Console.WriteLine($"🔑 使用命令行提供的 JoinToken");
}

// 配置服务
builder.Services.AddControllers();

// 注册 HttpClient 用于主节点发现
builder.Services.AddHttpClient<MasterDiscoveryService>();
builder.Services.AddSingleton<MasterDiscoveryService>();

// TCP 多主节点客户端配置
var masterEndpoints = new List<MasterEndpoint>();

// ========================================
// 🔍 主节点发现策略（按优先级）
// ========================================

// 优先级 1: 通过 HTTP URL 动态发现（推荐！）
var discoveryUrl = builder.Configuration.GetValue<string>("Discovery:Url");
var discoveryUrlArg = args.FirstOrDefault(a => a.StartsWith("--discovery-url=") || a.StartsWith("--master-url=") || a.StartsWith("--control-panel-url="));

if (!string.IsNullOrEmpty(discoveryUrlArg))
{
    discoveryUrl = discoveryUrlArg.Split('=')[1];
}

if (!string.IsNullOrEmpty(discoveryUrl))
{
    Console.WriteLine($"🔍 使用 HTTP 发现模式: {discoveryUrl}");
    Console.WriteLine("正在发现可用的主节点...");

    try
    {
        // 创建临时的 HttpClient 进行发现
        using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
        var discoveryService = new MasterDiscoveryService(
            builder.Services.BuildServiceProvider().GetRequiredService<ILogger<MasterDiscoveryService>>(),
            httpClient);

        var discoveredMasters = await discoveryService.DiscoverMastersAsync(discoveryUrl);

        if (discoveredMasters.Count > 0)
        {
            masterEndpoints = discoveredMasters.Select(m => new MasterEndpoint
            {
                Host = m.Host,
                Port = m.TcpPort,
                Priority = m.Priority
            }).ToList();

            Console.WriteLine($"✅ 发现了 {masterEndpoints.Count} 个主节点");
            foreach (var ep in masterEndpoints)
            {
                Console.WriteLine($"   - {ep.Host}:{ep.Port} (Priority: {ep.Priority})");
            }
        }
        else
        {
            Console.WriteLine("⚠️  未发现任何主节点，将使用配置文件或默认值");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"❌ HTTP 发现失败: {ex.Message}");
        Console.WriteLine("将尝试使用配置文件中的主节点配置...");
    }
}

// 优先级 2: 单主节点配置（向后兼容）
if (masterEndpoints.Count == 0)
{
    var singleHost = builder.Configuration.GetValue<string>("ControlPanel:Host");
    if (!string.IsNullOrEmpty(singleHost))
    {
        var singlePort = builder.Configuration.GetValue<int>("ControlPanel:Port", 9090);
        masterEndpoints.Add(new MasterEndpoint
        {
            Host = singleHost,
            Port = singlePort,
            Priority = 1
        });
        Console.WriteLine($"📝 使用配置文件单主节点: {singleHost}:{singlePort}");
    }
}

// 优先级 3: 多主节点配置
if (masterEndpoints.Count == 0)
{
    var multiMasterConfig = builder.Configuration.GetSection("ControlPanels").Get<List<MasterEndpoint>>();
    if (multiMasterConfig != null && multiMasterConfig.Count > 0)
    {
        masterEndpoints = multiMasterConfig;
        Console.WriteLine($"📝 使用配置文件多主节点: {masterEndpoints.Count} 个");
    }
}

// 如果没有配置，使用默认值
if (masterEndpoints.Count == 0)
{
    masterEndpoints.Add(new MasterEndpoint
    {
        Host = "localhost",
        Port = 9090,
        Priority = 1
    });
}

var connectionStrategy = builder.Configuration.GetValue<string>("ConnectionStrategy") ?? "ConnectAll";
var aesKeyString = builder.Configuration.GetValue<string>("ControlPanel:AesKey") ?? "0123456789ABCDEF";

// 使用与ControlApi相同的密钥派生方法
var salt = Encoding.UTF8.GetBytes("SumerCore-TCP"); // 与主节点相同的盐值
var derivedKey = EncryptionHelper.DeriveKeyFromPassword(aesKeyString, salt);
var aesKey = new byte[16]; // TcpProtocolConstants.AesKeyLength
Array.Copy(derivedKey, aesKey, Math.Min(derivedKey.Length, 16));

builder.Services.AddSingleton(sp =>
{
    var logger = sp.GetRequiredService<ILogger<TcpMultiMasterClient>>();
    return new TcpMultiMasterClient(logger, aesKey, masterEndpoints, connectionStrategy);
});

// 注册 TcpClient（向后兼容，使用第一个主节点）
builder.Services.AddSingleton(sp =>
{
    var logger = sp.GetRequiredService<ILogger<TcpClient>>();
    var firstEndpoint = masterEndpoints.FirstOrDefault() ?? new MasterEndpoint { Host = "localhost", Port = 9090 };
    return new TcpClient(logger, aesKey, firstEndpoint.Host, firstEndpoint.Port);
});

// 注册基础设施库
builder.Services.AddSingleton<GitLibrary>();
builder.Services.AddSingleton(sp =>
{
    var logger = sp.GetRequiredService<ILogger<DockerLibrary>>();
    return new DockerLibrary(logger);
});

// 注册服务
builder.Services.AddSingleton<NodeConfigPersistenceService>();
builder.Services.AddSingleton<HotRegistrationService>();
builder.Services.AddSingleton<NodeRegistrationService>();
builder.Services.AddSingleton<HeartbeatService>();
builder.Services.AddSingleton<TaskExecutor>();
builder.Services.AddSingleton<ProjectTypeDetector>();
builder.Services.AddSingleton<EnvironmentDetector>();
builder.Services.AddSingleton<EnvironmentInstaller>();

// 注册处理器
builder.Services.AddTransient<GitCloneHandler>();
builder.Services.AddTransient<BuildHandler>();
builder.Services.AddTransient<TestHandler>();
builder.Services.AddTransient<DeployDockerHandler>();
builder.Services.AddTransient<DeployK8sHandler>();
builder.Services.AddTransient<CleanupHandler>();
builder.Services.AddTransient<DockerDeployRemoteHandler>();
builder.Services.AddTransient<ArchiveArtifactsHandler>();

// 注册 Hosted Services
builder.Services.AddHostedService(sp => sp.GetRequiredService<NodeRegistrationService>());
builder.Services.AddHostedService(sp => sp.GetRequiredService<HeartbeatService>());

var app = builder.Build();

// ========================================
// 🔐 初始化加密密钥
// ========================================
var keyManagerLogger = app.Services.GetRequiredService<ILogger<EncryptionKeyManager>>();
var keyManager = new EncryptionKeyManager(keyManagerLogger);
var encryptionKey = keyManager.GetOrCreateEncryptionKey();

// 设置加密密钥到 EncryptionHelper
EncryptionHelper.SetEncryptionKey(encryptionKey);

app.Logger.LogInformation("🔐 加密系统已初始化");

// 配置 HTTP 请求管道
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

// 配置 TCP 消息处理
var tcpClient = app.Services.GetRequiredService<TcpMultiMasterClient>();
var taskExecutor = app.Services.GetRequiredService<TaskExecutor>();

tcpClient.OnMessageReceived += async (masterId, messageType, body) =>
{
    try
    {
        // 跳过注册相关的消息，让NodeRegistrationService处理
        if (messageType == TcpMessageType.RegisterResponse ||
            messageType == TcpMessageType.AuthResponse ||
            messageType == TcpMessageType.ConfigurationChanged)
        {
            return; // 这些消息由NodeRegistrationService处理
        }

        switch (messageType)
        {
            case TcpMessageType.WorkflowStepDispatch:
                if (body is WorkflowStepDispatchMessage dispatchMsg)
                {
                    app.Logger.LogInformation("收到来自主节点 {MasterId} 的任务分派: TaskId={TaskId}", masterId, dispatchMsg.TaskId);
                    // 异步执行任务
                    _ = Task.Run(async () => await taskExecutor.ExecuteTaskAsync(dispatchMsg));
                }
                break;

            case TcpMessageType.CleanupCommand:
                if (body is CleanupCommandMessage cleanupMsg)
                {
                    app.Logger.LogInformation("收到来自主节点 {MasterId} 的清理指令: TaskId={TaskId}", masterId, cleanupMsg.TaskId);
                    // 执行清理（可以在这里调用 CleanupHandler）
                }
                break;

            case TcpMessageType.ArtifactDownloadRequest:
                if (body is ArtifactDownloadRequestMessage downloadReq)
                {
                    app.Logger.LogInformation("收到产物下载请求: ArtifactId={ArtifactId}, ChunkIndex={ChunkIndex}",
                        downloadReq.ArtifactId, downloadReq.ChunkIndex);

                    try
                    {
                        // 读取文件分片
                        if (!File.Exists(downloadReq.FilePath))
                        {
                            var errorResponse = new ArtifactDownloadResponseMessage
                            {
                                ArtifactId = downloadReq.ArtifactId,
                                Success = false,
                                ErrorMessage = $"文件不存在: {downloadReq.FilePath}"
                            };
                            await tcpClient.SendToMasterAsync(masterId, TcpMessageType.ArtifactDownloadResponse, errorResponse);
                            break;
                        }

                        var fileInfo = new FileInfo(downloadReq.FilePath);
                        var totalFileSize = fileInfo.Length;
                        var totalChunks = (int)Math.Ceiling((double)totalFileSize / downloadReq.ChunkSize);

                        // 读取指定分片
                        await using var fileStream = new FileStream(downloadReq.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                        var offset = (long)downloadReq.ChunkIndex * downloadReq.ChunkSize;
                        fileStream.Seek(offset, SeekOrigin.Begin);

                        var buffer = new byte[Math.Min(downloadReq.ChunkSize, (int)(totalFileSize - offset))];
                        var bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length);

                        // 编码为 Base64
                        var base64Data = Convert.ToBase64String(buffer, 0, bytesRead);

                        var response = new ArtifactDownloadResponseMessage
                        {
                            ArtifactId = downloadReq.ArtifactId,
                            Success = true,
                            ChunkIndex = downloadReq.ChunkIndex,
                            TotalChunks = totalChunks,
                            FileDataBase64 = base64Data,
                            DataLength = bytesRead,
                            IsLastChunk = downloadReq.ChunkIndex == totalChunks - 1,
                            TotalFileSize = totalFileSize
                        };

                        await tcpClient.SendToMasterAsync(masterId, TcpMessageType.ArtifactDownloadResponse, response);
                        app.Logger.LogDebug("已发送产物分片: ArtifactId={ArtifactId}, Chunk={ChunkIndex}/{TotalChunks}",
                            downloadReq.ArtifactId, downloadReq.ChunkIndex, totalChunks);
                    }
                    catch (Exception ex)
                    {
                        app.Logger.LogError(ex, "处理产物下载请求失败: ArtifactId={ArtifactId}", downloadReq.ArtifactId);
                        var errorResponse = new ArtifactDownloadResponseMessage
                        {
                            ArtifactId = downloadReq.ArtifactId,
                            Success = false,
                            ErrorMessage = ex.Message
                        };
                        await tcpClient.SendToMasterAsync(masterId, TcpMessageType.ArtifactDownloadResponse, errorResponse);
                    }
                }
                break;

            default:
                app.Logger.LogInformation("收到来自主节点 {MasterId} 的消息类型: {MessageType}", masterId, messageType);
                break;
        }
    }
    catch (Exception ex)
    {
        app.Logger.LogError(ex, "处理来自主节点 {MasterId} 的TCP消息失败: MessageType={MessageType}", masterId, messageType);
    }

    await Task.CompletedTask;
};

tcpClient.OnConnected += async (masterId) =>
{
    app.Logger.LogInformation("✅ 已连接到主节点: {MasterId}", masterId);
    await Task.CompletedTask;
};

tcpClient.OnDisconnected += async (masterId) =>
{
    app.Logger.LogWarning("⚠️ 与主节点 {MasterId} 的连接已断开", masterId);
    await Task.CompletedTask;
};

// 确保工作目录存在
var workDirectory = builder.Configuration.GetValue<string>("Node:WorkDirectory") ?? "/tmp/sumer-devops";
if (!Directory.Exists(workDirectory))
{
    Directory.CreateDirectory(workDirectory);
    app.Logger.LogInformation("创建工作目录: {Directory}", workDirectory);
}

app.Logger.LogInformation("SumerCore DevOps 执行节点已启动");
app.Logger.LogInformation("配置的主节点数量: {Count}, 连接策略: {Strategy}", masterEndpoints.Count, connectionStrategy);
foreach (var endpoint in masterEndpoints)
{
    app.Logger.LogInformation("  - {Host}:{Port} (Priority: {Priority})", endpoint.Host, endpoint.Port, endpoint.Priority);
}

app.Run();

return 0;
